using System;
using System.Collections.Generic;

namespace IQIGame.Onigao.Framework.Serialization
{
    public static class SerializeByteBufUtil
    {
        public static void SerializeObject(this ByteBuf _buf, ISerializeByteBuf rObject)
        {
            _buf.WriteBool(rObject != null);
            if (rObject != null)
            {
                rObject.Serialize(_buf);
            }
        }

        public static bool DeSerializeObject<T>(this ByteBuf _buf, ref T rObject) where T : ISerializeByteBuf, new()
        {
            var bNotNull = _buf.ReadBool();
            if (bNotNull)
            {
                if (rObject == null)
                {
                    rObject = new T();
                }

                rObject.DeSerialize(_buf);
                return true;
            }
            return false;
        }

        public static T DeSerializeObject<T>(this ByteBuf _buf) where T : ISerializeByteBuf, new()
        {
            var bNotNull = _buf.ReadBool();
            if (bNotNull)
            {
                T rObject = new T();
                rObject.DeSerialize(_buf);
                return rObject;
            }
            return default;
        }

        public static void SerializeList<T>(this ByteBuf _buf, IReadOnlyList<T> rList) where T : ISerializeByteBuf
        {
            int count = rList?.Count ?? 0;
            _buf.WriteInt(count);
            if (count <= 0)
                return;
            Type t = typeof(T);
            for (int i = 0; i < rList.Count; i++)
            {
                if (t.IsValueType)
                {
                    rList[i].Serialize(_buf);
                }
                else
                {
                    SerializeObject(_buf, rList[i]);
                }
            }
        }

        /// <summary>
        /// 手动序列化调用，后期需删除，请使用带返回值的重载
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="_buf"></param>
        /// <param name="rList"></param>
        [Obsolete]
        public static void DeSerializeList<T>(this ByteBuf _buf, ref List<T> rList) where T : ISerializeByteBuf, new()
        {
            var nCount = _buf.ReadInt();
            //不能判断null，直接赋值，保证IReadOnlyList<T> rList一定是List，后面才能添加元素
            //反序列化一定内部创建对象，如果由外部创建，结果不可控。
            rList = new List<T>(nCount);

            for (int i = 0; i < nCount; i++)
            {
                T rObject = new T();
                DeSerializeObject(_buf, ref rObject);
                rList.Add(rObject);
            }
        }

        public static List<T> DeSerializeList<T>(this ByteBuf _buf) where T : ISerializeByteBuf, new()
        {
            var nCount = _buf.ReadInt();
            List<T> rList = new List<T>(nCount);
            if (nCount <= 0)
            {
                return rList;
            }
            Type t = typeof(T);
            for (int i = 0; i < nCount; i++)
            {
                T rObject = default;
                if (t.IsValueType)
                {
                    rObject.DeSerialize(_buf);
                }
                else
                {
                    rObject = DeSerializeObject<T>(_buf);
                }
                rList.Add(rObject);
            }

            return rList;
        }

        public static T[] DeSerializeArray<T>(this ByteBuf _buf) where T : ISerializeByteBuf, new()
        {
            var nCount = _buf.ReadInt();
            T[] array = new T[nCount];

            for (int i = 0; i < nCount; i++)
            {
                T rObject = new T();
                DeSerializeObject(_buf, ref rObject);
                array[i] = rObject;
            }

            return array;
        }

        public static void SerializeListInt(this ByteBuf _buf, IReadOnlyList<int> rList)
        {
            int count = rList?.Count ?? 0;
            _buf.WriteInt(count);
            if (count <= 0)
                return;
            for (int i = 0; i < rList.Count; i++)
            {
                _buf.WriteInt(rList[i]);
            }
        }

        public static List<int> DeSerializeListInt(this ByteBuf _buf)
        {
            var nCount = _buf.ReadInt();
            List<int> rList = new List<int>(nCount);

            for (int i = 0; i < nCount; i++)
            {
                rList.Add(_buf.ReadInt());
            }

            return rList;
        }

        public static void SerializeListLong(this ByteBuf _buf, IReadOnlyList<long> rList)
        {
            int count = rList?.Count ?? 0;
            _buf.WriteInt(count);
            if (count <= 0)
                return;
            for (int i = 0; i < rList.Count; i++)
            {
                _buf.WriteLong(rList[i]);
            }
        }

        public static List<long> DeSerializeListLong(this ByteBuf _buf)
        {
            var nCount = _buf.ReadInt();
            List<long> rList = new List<long>(nCount);

            for (int i = 0; i < nCount; i++)
            {
                rList.Add(_buf.ReadLong());
            }

            return rList;
        }

        public static void SerializeListShort(this ByteBuf _buf, IReadOnlyList<short> rList)
        {
            int count = rList?.Count ?? 0;
            _buf.WriteInt(count);
            if (count <= 0)
                return;
            for (int i = 0; i < rList.Count; i++)
            {
                _buf.WriteShort(rList[i]);
            }
        }

        public static List<short> DeSerializeListShort(this ByteBuf _buf)
        {
            var nCount = _buf.ReadInt();
            List<short> rList = new List<short>(nCount);

            for (int i = 0; i < nCount; i++)
            {
                rList.Add(_buf.ReadShort());
            }

            return rList;
        }

        public static void SerializeListUshort(this ByteBuf _buf, IReadOnlyList<ushort> rList)
        {
            int count = rList?.Count ?? 0;
            _buf.WriteInt(count);
            if (count <= 0)
                return;
            for (int i = 0; i < rList.Count; i++)
            {
                _buf.WriteShort((short)rList[i]);
            }
        }

        public static List<ushort> DeSerializeListUshort(this ByteBuf _buf)
        {
            var nCount = _buf.ReadInt();
            List<ushort> rList = new List<ushort>(nCount);

            for (int i = 0; i < nCount; i++)
            {
                rList.Add((ushort)_buf.ReadShort());
            }

            return rList;
        }

        public static void SerializeListString(this ByteBuf _buf, IReadOnlyList<string> rList)
        {
            int count = rList?.Count ?? 0;
            _buf.WriteInt(count);
            if (count <= 0)
                return;
            for (int i = 0; i < rList.Count; i++)
            {
                _buf.WriteString(rList[i]);
            }
        }

        public static List<string> DeSerializeListString(this ByteBuf _buf)
        {
            var nCount = _buf.ReadInt();
            List<string> rList = new List<string>(nCount);

            for (int i = 0; i < nCount; i++)
            {
                rList.Add(_buf.ReadString());
            }

            return rList;
        }
    }
}
